﻿using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Primitives;
using SaaS.Core;
using SaaS.Cache.Auths;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using XCore.Authorization;
using XCore.Web.Filter;
using XCore.Extensions;
using SaaS.Core.Logger;
using XCore.Logger;

namespace Web.Admin
{
    /// <summary>
    /// 授权过滤器
    /// </summary>
    public class AdminAuthorizationFilter : ApiResultFilterAttribute
    {
        private readonly AdminAuthCacheService _adminAuthCacheService;
        private readonly TraceLogger _logger;
        public AdminAuthorizationFilter(AdminAuthCacheService adminAuthCacheService, TraceLogger logger)
        {
            _adminAuthCacheService = adminAuthCacheService;
            _logger = logger;
        }
        /// <summary>
        /// 执行之后
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task OnResultExecutionAsync(ResultExecutingContext context)
        {
            //记录日志
            var disable = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.GetCustomAttributes(typeof(DisableAuditingAttribute), false).FirstOrDefault();
            if (disable == null) _logger.Log(context.HttpContext.Request.Path.Value);
            return base.OnResultExecutionAsync(context);
        }
        /// <summary>
        /// 执行之前
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            MethodInfo method = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo;
            //游客标记、无需登录访问
            if (method.GetCustomAttributes(typeof(GuestAttribute), false).FirstOrDefault() != null) return base.OnActionExecutionAsync(context, next);
            else
            {
                //# 授权验证
                StringValues token = context.HttpContext.Request.Headers.Where(c => c.Key == CoreSetting.Token).FirstOrDefault().Value;
                if (token.Count == 0) throw new AuthorizationException("用户未登陆");
                int adminId = context.HttpContext.GetUserId("AdminId");
                if (adminId == 0) throw new AuthorizationException("用户未登陆");
                if (!_adminAuthCacheService.CheckTenantToken(adminId, token)) throw new AuthorizationException("会员登录过期");
                //# 功能验证
                // 超级管理员过滤功能权限
                if (context.HttpContext.GetClaimValue("IsDefault").ToBool()) return base.OnActionExecutionAsync(context, next);
                PermissionAttribute permission = method.GetCustomAttributes(typeof(PermissionAttribute), false).FirstOrDefault() as PermissionAttribute;
                if (permission == null) return base.OnActionExecutionAsync(context, next);
                int roleId = context.HttpContext.GetClaimValue("RoleId").ToInt();
                if (roleId == 0) throw new AuthorizationException("会员未授权");
                if (!_adminAuthCacheService.IsPermission(roleId, permission.Permission)) throw new AuthorizationException($"用户没有以下权限：{string.Join("\n", permission.Permission)}");
                return base.OnActionExecutionAsync(context, next);
            }
        }
    }
}
